package com.example.weixinpayment.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.weixinpayment.constant.enums.OrderStatus;
import com.example.weixinpayment.entity.OrderInfo;
import com.example.weixinpayment.entity.Product;
import com.example.weixinpayment.mapper.OrderInfoMapper;
import com.example.weixinpayment.service.OrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.weixinpayment.service.ProductService;
import com.example.weixinpayment.util.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private ProductService productService;

    @Override
    public OrderInfo createOrderByProductId(Long productId) {

        //根据产品id获取产品信息
        Product product = productService.getById(productId);

        //根据产品信息查询是否由存在该产品的未支付订单信息
        OrderInfo noPayOrder = this.getNoPayOrderByProduct(product);

        //如果存在未支付的该产品订单信息 直接返回 否则新建订单
        if (ObjectUtil.isNotEmpty(noPayOrder)){
            return noPayOrder;
        }
        //订单信息
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setTitle(product.getTitle());
        orderInfo.setOrderNo(OrderNoUtils.getOrderNo());
        orderInfo.setProductId(productId);
        orderInfo.setTotalFee(product.getPrice());
        orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType());

        baseMapper.insert(orderInfo);

        return orderInfo;
    }

    @Override
    public void updateCodeUrl(String orderNo, String codeUrl) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCodeUrl(codeUrl);
        orderInfo.setCodeUrlExpireTime(Date.from(LocalDateTime.now().plusHours(2).atZone(ZoneId.systemDefault()).toInstant()));

        int update = baseMapper.update(orderInfo, new QueryWrapper<OrderInfo>().eq("order_no", orderNo));

        if (update != 1){
            throw new RuntimeException("更新订单二维码失败");
        }
    }

    @Override
    public List<OrderInfo> listOrderByCreateTimeDesc() {
        return baseMapper.selectList(new QueryWrapper<OrderInfo>().orderByDesc("create_time"));
    }

    @Override
    public void updateOrderStatus(String orderNo, OrderStatus status) {
        log.info("update order status to {}", status.getType());
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderStatus(status.getType());

        baseMapper.update(orderInfo, new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
    }

    @Override
    public String getOrderStatus(String orderNo) {
        OrderInfo orderInfo = baseMapper.selectOne(new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
        if (ObjectUtil.isEmpty(orderInfo)){
            return null;
        }
        return orderInfo.getOrderStatus();
    }

    @Override
    public List<OrderInfo> getNoPayOrderByDuration(int minutes) {
        Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));

        List<OrderInfo> orderInfoList = baseMapper.selectList(new QueryWrapper<OrderInfo>().eq("order_status", OrderStatus.NOTPAY.getType())
                .le("create_time", instant));
        return orderInfoList;
    }

    @Override
    public OrderInfo getOrderByOrderNo(String orderNo) {
        return baseMapper.selectOne(new QueryWrapper<OrderInfo>().eq("order_no", orderNo));
    }

    /**
     * @description: 根据产品信息查询未支付订单
     * @param: product
     * @return: com.example.weixinpayment.entity.OrderInfo
     * @author: 刘助政
     * @date: 2021/12/30 17:32
     * */
    private OrderInfo getNoPayOrderByProduct(Product product) {
        return baseMapper.selectOne(new QueryWrapper<OrderInfo>().eq("product_id" , product.getId())
                .eq("total_fee", product.getPrice())
                .eq("order_status", OrderStatus.NOTPAY.getType()));
    }
}
